﻿using ClumsyWords.Model;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace ClumsyWords.ViewModel
{
    public class MainViewModel : ViewModelBase
    {

        public MainViewModel()
        {
            //this.FileStorage = collectionsFileStorage;
            //this.AllItems = new ObservableCollection<ItemsCollection<TermDefinition>>();
            //this.PopularItems = new ItemsCollection<TermDefinition>("Popular", new ObservableCollection<TermDefinition>());
            //this.GeneratePopularItems();
            this.RecentItems = new ObservableCollection<TermDefinition>();
            this.FavouriteItems = new ObservableCollection<TermDefinition>();
            //this.AllItems.Add(this.RecentItems);
            //this.AllItems.Add(this.FavouriteItems);
            this.SearchResult = new TermDefinition();
        }

        //public IFileStorage<ObservableCollection<TermDefinition>> FileStorage { get; private set; }

        //public ObservableCollection<ItemsCollection<TermDefinition>> AllItems { get; private set; }

        /// <summary>
        /// A collection for items that are popular.
        /// </summary>
        //private ObservableCollection<TermDefinition> _popularItems;
        //public ObservableCollection<TermDefinition> PopularItems
        //{
        //    get { return this._popularItems; }
        //    private set
        //    {
        //        this._popularItems = value;
        //        NotifyPropertyChanged("PopularItems");
        //    }
        //}

        //private void GeneratePopularItems()
        //{
        //    string[] sampleWords = new string[] { "joy", " playful", " park", " fluctuate", "near", "up", "fast" };
        //    foreach (var word in sampleWords)
        //    {
        //        //var termDefinition = await this.CheckWordAsync("http://www.stands4.com/services/v2/defs.php?uid=3021tokenid=vE8RzRNRjAHQIJuR&word=" + word);
        //        //this.PopularItems.Add(termDefinition);
        //    }
        //    this.AllItems.Add(this.PopularItems);
        //}


        /// <summary>
        /// A collection for items that have been recently looked up.
        /// </summary>
        private ObservableCollection<TermDefinition> _recentItems;
        public ObservableCollection<TermDefinition> RecentItems 
        {
            get { return this._recentItems; }
            private set
            {
                this._recentItems = value;
                NotifyPropertyChanged("RecentItems");
            }
        }

        /// <summary>
        /// A collection for items that have been added to favourites list
        /// </summary>
        private ObservableCollection<TermDefinition> _favouriteItems;
        public ObservableCollection<TermDefinition> FavouriteItems 
        {
            get { return this._favouriteItems; }
            private set
            {
                this._favouriteItems = value;
                NotifyPropertyChanged("FavouriteItems");
            }
        }

        /// <summary>
        /// The result of the last quick search.
        /// </summary>
        private TermDefinition _searchResult;
        public TermDefinition SearchResult
        {
            get { return this._searchResult; }

            set
            {
                this._searchResult = value;
                NotifyPropertyChanged("SearchResult");
            }
        }

        /// <summary>
        /// The current term that is being searched for.
        /// </summary>
        private string _searchTerm;
        public string SearchTerm
        {
            get { return this._searchTerm; }

            set
            {
                this._searchTerm = value;
                NotifyPropertyChanged("SearchTerm");
            }
        }

        /// <summary>
        /// Sends a request to the STANDS4 API and presents the result as a SearchResult
        /// </summary>
        /// <param name="word">The word that is being searched for</param>
        /// <returns></returns>
        public async Task<TermDefinition> CheckWordAsync(string url)
        {
            //PartOfSpeechConverter converter = new PartOfSpeechConverter();

            HttpClient client = new HttpClient();

            HttpResponseMessage response = await client.GetAsync(url);
            string responseText = await response.Content.ReadAsStringAsync();
            //TODO : Check if there is a responseText before parsing it.

            XDocument doc = XDocument.Parse(responseText);
            if (doc.Element("results").Elements("results") != null)
            {
                //Composing the search result from xml

                var term = doc.Element("results").Elements("result").First().Element("term").Value.ToString();
                var termPropertiesList = (from _props in doc.Element("results").Elements("result")
                                          select new TermProperties
                                          {
                                              Term = _props.Element("term").Value.ToString(),
                                              Definition = _props.Element("definition").Value.ToString(),
                                              Example = _props.Element("example").Value.ToString(),
                                              PartOfSpeech = this.PartOfSpeechStringConversion(_props.Element("partofspeech").Value.ToString())
                                          })
                                          //.GroupBy(x => x.PartOfSpeech)
                                          //.Select(g => new Group<PartOfSpeech,TermProperties>(g.Key, g))
                                          //.Select(g => new TermPropertiesGroup(g.Key, g.Key, g, true/false))
                                            .ToList();

                TermDefinition result = new TermDefinition(term, termPropertiesList);

                return result;
            }
            return default(TermDefinition);

            //TODO : Check if sth has failed.
        }

        public bool IsDataLoaded
        {
            get;
            private set;
        }

        /// <summary>
        /// Loads the RecentItems and FavouriteItems from isolated storage
        /// </summary>
        public async void LoadData()
        {
            CustomDataSerializer<ObservableCollection<TermDefinition>> serializer = new CustomDataSerializer<ObservableCollection<TermDefinition>>();
            var recentData = await serializer.LoadAsync("recent.store");
            if (recentData != null)
                this.RecentItems = recentData;

            var favourites = await serializer.LoadAsync("favourites.store");
            if (favourites != null) 
                this.FavouriteItems = favourites;

            this.IsDataLoaded = true;
        }

        private PartOfSpeech PartOfSpeechStringConversion(string key)
        {
            const string NounString1 = "noun";
            const string NounString2 = ""; //idk
            const string PronounString = "pronoun";
            const string AdjectiveString1 = "adj";
            const string AdjectiveString2 = "adjective";
            const string VerbString1 = "verb";
            const string AdverbString1 = "adv";
            const string AdverbString2 = "adverb";
            const string PrepositionString1 = "prep";
            const string PrepositionString2 = "preposition";
            const string ConjunctionString1 = "conjunction";
            const string InterjectionString1 = "interjection";

            switch (key.ToLower())
            {
                case NounString1:
                case NounString2:
                    return PartOfSpeech.noun;
                case PronounString: 
                    return PartOfSpeech.pronoun;
                case AdjectiveString1:
                case AdjectiveString2:
                    return PartOfSpeech.adjective;
                case AdverbString1:
                case AdverbString2:
                    return PartOfSpeech.adverb;
                case VerbString1:
                    return PartOfSpeech.verb;
                case PrepositionString1:
                case PrepositionString2:
                    return PartOfSpeech.preposition;
                case ConjunctionString1:
                    return PartOfSpeech.conjunction;
                case InterjectionString1:
                    return PartOfSpeech.interjection;
                default: return PartOfSpeech.unidentified;
            }
        }
    }
}
